import { FC, useState } from 'react'
import { observer } from 'mobx-react'
import styles from './PersonalizedGeneration.module.scss'
import { useColorVar, useStyles } from '@/hooks/styles'
import { ViewTitle } from '@/components/universal/ViewTitle/ViewTitle'
import {
  Button,
  Divider,
  Image,
  Input,
  InputNumber,
  message,
  Segmented,
  Slider,
  Spin,
  Upload,
} from 'antd'
import StyleIt from '@/assets/images/StyleIt.svg'
import { BlockTitle } from '@/components/universal/BlockTitle/BlockTitle'
import { SvgIcon } from '@/components/icons'
import { IconImage, IconPrompt } from '@/components/icons/IconStyleFactory'
import { useGenStore, useGraphStore, useRoughStore } from '@/hooks'
import { baseUrl, token, uploadUrl } from '@/config'
import {
  DownloadOutlined,
  LoadingOutlined,
  UploadOutlined,
} from '@ant-design/icons'
import { ImageItemForTest } from '@/components/1RoughMachining/ImageList'
import { AxisControl } from '@/components/4PersonalizedGeneration/AxisControl'
import axios from 'axios'
import { mobxProxyTrans } from '@/utils/basic'
import { addImageNodeInCanvas } from '@/components/3FineMachining/utils'
import { ImageNode } from '@/components/3FineMachining/ImageNode'

const { TextArea } = Input
export const PersonalizedGeneration: FC = observer(() => {
  const c = useColorVar()
  const styleClass = useStyles(styles)
  const [messageApi, contextHolder] = message.useMessage()
  const rough = useRoughStore()
  const genStore = useGenStore()
  const graphStore = useGraphStore()

  const [loading, setLoading] = useState<boolean>(false)

  const handleStyleIt = async () => {
    if (genStore.applyStyle === null) {
      messageApi.info({ key: '4', content: 'Please select a style to apply!' })
      return
    }
    const applyStyle = rough.styleList.filter(
      (style) => style.id === genStore.applyStyle
    )[0]
    setLoading(true)
    switch (genStore.mode) {
      case 'Prompt':
        await axios
          .post(`${baseUrl}/fine/generate`, {
            negativePrompt: genStore.getNegativePrompt(),
            description: genStore.getPositivePrompt(), // 此处description是提示词，不是风格描述
            image_list: applyStyle.image_list,
            weight: genStore.renderLevel / 100, // 风格的渲染程度
            weight_list: applyStyle.weight,
            target_weight: [genStore.strength],
            batch_size: 4, // 生成数量
            num_each_bath: 4,
          })
          .then((res) => {
            console.log(res.data.data)
            const result = []
            for (let i = 0; i < res.data.data[0].length; i++) {
              result.push(res.data.data[0][i]['url'])
            }
            setLoading(false)
            genStore.setGeneratedImage(result)
            messageApi.success({ key: '4', content: 'Done!' })
            return
          })
          .catch((error) => {
            setLoading(false)
            messageApi.error({ key: '4', content: 'Error!' })
            console.log('error', error)
            return
          })
        break
      case 'Image':
        if (genStore.originalImage === '') {
          messageApi.info({
            key: '4',
            content: 'Please upload the original image!',
          })
          setLoading(false)
          return
        }
        await axios
          .post(`${baseUrl}/fine/generate`, {
            description: '', // 此处description是提示词，不是风格描述
            image_list: applyStyle.image_list,
            weight: 0.95, // 风格的渲染程度
            weight_list: applyStyle.weight,
            target_weight: [genStore.strength],
            batch_size: 4, // 每一个目标风格强度的生成数量
            num_each_bath: 1,
            image: genStore.originalImage,
            denoising_strength: genStore.modificationLevel / 100, // 原图的修改程度
            guidanceScale: 7.5,
            num_inference_steps: 30, // 采样步骤
          })
          .then((res) => {
            // console.log(res.data.data)
            const result = []
            for (let i = 0; i < res.data.data[0].length; i++) {
              result.push(res.data.data[0][i]['url'])
            }
            setLoading(false)
            genStore.setGeneratedImage(result)
            messageApi.success({ key: '4', content: 'Done!' })
            return
          })
          .catch((error) => {
            setLoading(false)
            messageApi.error({ key: '4', content: 'Error!' })
            console.log('error', error)
            return
          })
        break
    }
  }

  const onReset = () => {
    genStore.setMode('Prompt')
    genStore.setApplyStyle(null)
    genStore.setStrength(0.5)
    genStore.setPositivePrompt('Positive: ')
    genStore.setNegativePrompt('Negative: ')
    genStore.setRenderLevel(40)
    genStore.setOriginalImage('')
    genStore.setModificationLevel(70)
    genStore.setGeneratedImage(['', '', '', ''])
  }

  return (
    <div {...styleClass(['layout'])}>
      {contextHolder}
      <ViewTitle text={'Personalized Generation'} />
      <div {...styleClass(['content'])}>
        {/* mode */}
        <div {...styleClass(['setting'])}>
          <div {...styleClass(['setting-title'])}>Style Rendering Mode:</div>
          <div>
            <Segmented
              options={[
                { label: 'Prompt', value: 'Prompt' },
                { label: 'Image', value: 'Image' },
              ]}
              value={genStore.mode}
              onChange={(v) => genStore.setMode(v as 'Prompt' | 'Image')}
            />
          </div>
        </div>
        {/* style strength */}
        <div {...styleClass(['setting'])}>
          <div {...styleClass(['setting-title'])}>Style Strength:</div>
          <AxisControl />
        </div>
        {/* Prompt */}
        <div {...styleClass(['block1'])}>
          <BlockTitle
            title={'Prompt'}
            icon={<SvgIcon icon={IconPrompt} />}
            description={'Prompt + Style'}
            barWidth={56}
          />
          <TextArea
            {...styleClass(['block1-textarea1'])}
            // autoSize={{ minRows: 2, maxRows: 2 }}
            value={genStore.positivePrompt}
            onChange={(e) => genStore.setPositivePrompt(e.target.value)}
          />
          <TextArea
            {...styleClass(['block1-textarea2'])}
            // autoSize={{ minRows: 2, maxRows: 2 }}
            value={genStore.negativePrompt}
            onChange={(e) => genStore.setNegativePrompt(e.target.value)}
          />
          <div {...styleClass(['block1-render-layout'])}>
            <div {...styleClass(['block1-render-text'])}>Rendering Level</div>
            <div {...styleClass(['block1-render-slider-layout'])}>
              <Slider
                min={0}
                max={100}
                onChange={(newV) => genStore.setRenderLevel(newV)}
                value={
                  typeof genStore.renderLevel === 'number'
                    ? genStore.renderLevel
                    : 40
                }
                {...styleClass(['block1-render-slider-slider'])}
              />
              <InputNumber
                size={'small'}
                min={0}
                max={100}
                value={genStore.renderLevel}
                onChange={(newV) => genStore.setRenderLevel(newV)}
                {...styleClass(['block1-render-slider-input'])}
              />
            </div>
          </div>
        </div>
        {/* Image */}
        <div {...styleClass(['block2'])}>
          <BlockTitle
            title={'Image'}
            icon={<SvgIcon icon={IconImage} />}
            description={'Image + Style'}
            barWidth={47}
          />
          <div {...styleClass(['block2-upload'])}>
            <ImageItemForTest
              url={genStore.originalImage}
              index={999}
              onDelete={() => genStore.setOriginalImage('')}
            />
            <Upload
              accept="image/*"
              headers={{ Authorization: token }}
              action={uploadUrl}
              onChange={(file) => {
                if ('response' in file.file) {
                  const url = file.file.response.data as string
                  genStore.setOriginalImage(url)
                }
              }}
            >
              <Button
                // icon={<UploadOutlined rev={null} />}
                {...styleClass(['block2-upload-right-button'])}
              >
                <div {...styleClass(['block2-upload-right-button-text'])}>
                  <UploadOutlined rev={null} style={{ marginRight: 8 }} />
                  Upload
                </div>
              </Button>
            </Upload>
          </div>
          <div {...styleClass(['block2-modification-layout'])}>
            <div {...styleClass(['block2-modification-text'])}>
              Modification Level
            </div>
            <div {...styleClass(['block2-modification-slider-layout'])}>
              <Slider
                min={0}
                max={100}
                onChange={(newV) => genStore.setModificationLevel(newV)}
                value={
                  typeof genStore.modificationLevel === 'number'
                    ? genStore.modificationLevel
                    : 70
                }
                {...styleClass(['block2-modification-slider-slider'])}
              />
              <InputNumber
                size={'small'}
                min={0}
                max={100}
                value={genStore.modificationLevel}
                onChange={(newV) => genStore.setModificationLevel(newV)}
                {...styleClass(['block2-modification-slider-input'])}
              />
            </div>
          </div>
        </div>

        <div {...styleClass(['button-group'])}>
          <Button
            type={'primary'}
            {...styleClass(['button-group-button1'])}
            onClick={() => handleStyleIt()}
          >
            <div {...styleClass(['button-group-button1-content'])}>
              <Image
                src={StyleIt}
                width={20}
                height={20}
                preview={false}
                style={{ marginTop: -5 }}
              />
              <div {...styleClass(['button-group-text'])}>Style It!</div>
            </div>
          </Button>
          <Button {...styleClass(['button-group-button2'])}>
            <div
              {...styleClass(['button-group-text'], { color: '#AD9F67' })}
              onClick={() => onReset()}
            >
              Reset
            </div>
          </Button>
        </div>

        <Divider style={{ margin: '5px 0' }}></Divider>

        <div {...styleClass(['temp'])}>
          <div {...styleClass(['temp-item'])}>
            <GenImage url={genStore.generatedImage[0]} loading={loading} />
          </div>
          <div {...styleClass(['temp-item'])}>
            <GenImage url={genStore.generatedImage[1]} loading={loading} />
          </div>
          <div {...styleClass(['temp-item'])}>
            <GenImage url={genStore.generatedImage[2]} loading={loading} />
          </div>
          <div {...styleClass(['temp-item'])}>
            <GenImage url={genStore.generatedImage[3]} loading={loading} />
          </div>
        </div>

        <div {...styleClass(['footer'])}>
          <Upload
            multiple={true}
            accept="image/*"
            headers={{ Authorization: token }}
            action={uploadUrl}
            onChange={(file) => {
              if ('response' in file.file) {
                const url = file.file.response.data as string
                // graphStore.addImageData(url)
                // rough.addReference(url)
                const temp = graphStore.graph.getNodes()
                addImageNodeInCanvas({
                  graph: graphStore.graph,
                  imageID: url,
                  component: ({ node, graph }) => (
                    <ImageNode
                      node={node}
                      graph={graph}
                      imageID={url}
                      url={url}
                    />
                  ),
                  position: [
                    72 + (temp.length % 10) * 104,
                    278 + Math.trunc(temp.length / 10) * 86,
                  ],
                })
              }
            }}
          >
            <Button
              // icon={<UploadOutlined rev={null} />}
              {...styleClass(['block2-upload-right-button'])}
            >
              <div {...styleClass(['block2-upload-right-button-text'])}>
                <DownloadOutlined rev={null} style={{ marginRight: 8 }} />
                Download
              </div>
            </Button>
          </Upload>
        </div>
      </div>
    </div>
  )
})

interface IGenImage {
  url: string
  loading: boolean
}
const GenImage: FC<IGenImage> = observer(({ url, loading }) => {
  return (
    <>
      {loading ? (
        <Spin
          indicator={
            <LoadingOutlined style={{ fontSize: 28 }} spin rev={'zmx'} />
          }
        />
      ) : (
        <Image
          src={
            url === ''
              ? 'https://s3.bmp.ovh/imgs/2024/03/12/a4aecd731a9333e7.png'
              : url
          }
          width={84}
          height={84}
          draggable={false}
        />
      )}
    </>
  )
})
